home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1991: Code Warrior / bincue / Code Warrior.bin / Tools & Apps (Moof!) / Testing & Debugging / Report Error 1.1 / dialogUtilities.c next >
Encoding:
C/C++ Source or Header  |  1991-08-27  |  10.6 KB  |  359 lines  |  [TEXT/KAHL]

  1. /*================================================================================
  2.     dialogUtilities.c
  3.     version 1.1
  4.     
  5.     Greg Anderson
  6.     28 June 1991
  7.     greggor@apple.com
  8.         
  9.     This file contains various and sundry dialog box utility routines
  10.     
  11. ================================================================================*/
  12. #include "dialogUtilities.h"
  13.  
  14. #ifndef __TYPES__
  15.     #include <Types.h>
  16. #endif
  17. #ifndef __SYSEQU__
  18.     #include <SysEqu.h>
  19. #endif
  20. #ifndef __ERRORS__
  21.     #include <Errors.h>
  22. #endif
  23. #ifndef __MEMORY__
  24.     #include <Memory.h>
  25. #endif
  26. #ifndef __RESOURCES__
  27.     #include <Resources.h>
  28. #endif
  29.  
  30. /*
  31. #include <stdio.h>
  32. #include <string.h>
  33. */
  34. #ifndef __QUICKDRAW__
  35.     #include <Quickdraw.h>
  36. #endif
  37. #ifndef __CONTROLS__
  38.     #include <Controls.h>
  39. #endif
  40. #ifndef __DIALOGS__
  41.     #include <Dialogs.h>
  42. #endif
  43.  
  44. /*
  45. // I don't like these globals
  46. */
  47. short gDefaultButton = 1;
  48. short gDefaultUserItem = 0;
  49.  
  50. /*--------------------------------------------------------------------------------
  51.     Center the specified dialog box & show it
  52.     
  53.     This code centers the dialog box on the main monitor (the one with the
  54.     menu bar) such that 1/3rd of the empty space left on that screen is
  55.     above the dialog and 2/3rds of it is below the dialog
  56.  
  57.     Note:
  58.     
  59.     This routine looks at MBarHeight to correctly calculate the
  60.     horizontal position of the dialog box.  Accessing low memory
  61.     globals is generally an evil thing to do, but in this case there\
  62.     is no good alternative.
  63. --------------------------------------------------------------------------------*/
  64. pascal void CenterAndShowDialog(DialogPtr dlog)
  65. {
  66.     short            menuHeight;
  67.     short            dlogWidth;
  68.     short            dlogHeight;
  69.     short            scrnWidth;
  70.     short            scrnHeight;
  71.     short            newDlogX;
  72.     short            newDlogY;
  73.     
  74.     /*
  75.     // Look at the low memory global 'MBarHeight' to determine the
  76.     // height of the menu bar (in pixels)
  77.     */
  78.     menuHeight = *((short*)MBarHeight);
  79.     /*
  80.     // Calculate the size of the dialog box and the main screen
  81.     // (without the menu bar)
  82.     */
  83.     dlogWidth    = (dlog->portRect.right - dlog->portRect.left);
  84.     dlogHeight    = (dlog->portRect.bottom - dlog->portRect.top);
  85.     scrnWidth    = (qd.screenBits.bounds.right - qd.screenBits.bounds.left);
  86.     scrnHeight    = (qd.screenBits.bounds.bottom - qd.screenBits.bounds.top) - menuHeight;
  87.     /*
  88.     // Quick check: don't leave any empty space if the dialog is
  89.     // too large to fit on the main screen.  This sanity check
  90.     // really should not be necessary, though, as all dialog boxes
  91.     // should fit on 9" screens
  92.     */
  93.     if( dlogHeight > scrnHeight)
  94.         dlogHeight = scrnHeight;
  95.     /*
  96.     // Calculate the menu's new location
  97.     */
  98.     newDlogX = qd.screenBits.bounds.left + (scrnWidth - dlogWidth) / 2;
  99.     newDlogY = qd.screenBits.bounds.top + menuHeight + (scrnHeight - dlogHeight) / 3;
  100.     /*
  101.     // Move the dialog and show it
  102.     */
  103.     MoveWindow(dlog,newDlogX,newDlogY,false);
  104.     ShowWindow(dlog);
  105. }
  106.  
  107. /*--------------------------------------------------------------------------------
  108.     Creates a new useritem in the specified dialog box & returns its item number
  109. --------------------------------------------------------------------------------*/
  110. pascal short AddNewUserItem( DialogPtr dlog )
  111. {
  112.     DialogPeek        theDialog        = (DialogPeek)dlog;
  113.     short**            itemHandle        = (short**)theDialog->items;
  114.     short            nItems            = **itemHandle + 1;
  115.     short            newItem            = 0;
  116.     DITLitem*        ditlPtr;
  117.     Size            itemHandleSize;
  118.     
  119.     itemHandleSize = GetHandleSize( (Handle)itemHandle );
  120.     SetHandleSize( (Handle)itemHandle, itemHandleSize + sizeof(DITLitem) );
  121.     if( MemError() == noErr )
  122.     {
  123.         /*
  124.         // We dereference the (potentially) unlocked itemHandle
  125.         // here; don't do any memory-moving calls until we've
  126.         // initialized the new DITL item
  127.         */
  128.         ditlPtr = (DITLitem*) ( (*itemHandle) + (itemHandleSize / sizeof(short)) );
  129.         /*
  130.         // Fill in the new fields
  131.         */
  132.         ditlPtr->placeholder = 0;
  133.         ditlPtr->itemType = userItem;
  134.         ditlPtr->extraLength = 0;
  135.         /*
  136.         // Remember / record the new number of items
  137.         */
  138.         newItem = nItems + 1;
  139.         **itemHandle = newItem - 1;
  140.     }
  141.     
  142.     return newItem;
  143. }
  144.  
  145. /*--------------------------------------------------------------------------------
  146.     Draw the thick rounded rectangle around the default button
  147.  
  148.     This routine uses Keith Rollin's algorithm, as presented in the
  149.     USENET Guide to Programming the Macintosh.  I have modified the
  150.     basic algorithm only slightly--I add two to the calculated
  151.     'buttonOval' value.  This gets better results, particularly for
  152.     buttons of the default size (18 points).
  153. --------------------------------------------------------------------------------*/
  154. pascal void DrawDefaultProc(DialogPtr dlog, short item)
  155. {
  156.     short                type;
  157.     Handle                userHandle;
  158.     ControlHandle        buttonHandle = nil;
  159.     Rect                outlineBox;
  160.     Rect                buttonBox;
  161.     PenState            saveState;
  162.     short                buttonOval;
  163.     
  164.     GetPenState( &saveState );
  165.     GetDItem(dlog, item, &type, &userHandle, &outlineBox);
  166.     /*
  167.     // We want to draw the thick line with a normal
  168.     // pen pattern that is 3 pixels wide
  169.     */
  170.     PenNormal();
  171.     PenSize(3,3);
  172.     /*
  173.     // If the button we are outlining is disabled,
  174.     // draw the outline with a gray pattern.
  175.     // (Don't forget to check if the default button
  176.     // is disabled in your filterProc before translating
  177.     // RETURN to a button click)
  178.     //
  179.     // The bad news is that we don't get a refCon to
  180.     // go with our userItem, so we must resort to
  181.     // the use of a global to keep track of the
  182.     // default button.  This isn't so bad, since an
  183.     // application usually shouldn't have a
  184.     // modal dialog box bring up another modal dialog
  185.     // box.  If your application does, just make sure
  186.     // that you either (a) save & restore gDefaultButton,
  187.     // or (b) make sure that both modal dialog boxes
  188.     // use item #1 for their default button.
  189.     */
  190.     GetDItem(dlog, gDefaultButton, &type, (Handle*)&buttonHandle, &buttonBox);
  191.     if( buttonHandle )
  192.     {
  193.         if( (*buttonHandle)->contrlHilite == 255 )
  194.             PenPat(qd.gray);
  195.     }    
  196.     /*
  197.     // Calculate the curvature to use and draw the thick line
  198.     */
  199.     buttonOval = 2 + (outlineBox.bottom - outlineBox.top) / 2;
  200.     FrameRoundRect(&outlineBox,buttonOval,buttonOval);
  201.     
  202.     SetPenState( &saveState );
  203. }
  204.  
  205. /*--------------------------------------------------------------------------------
  206.     This function creates a useritem around the default button & installs
  207.     a drawing proc that draws the default border around it.
  208.     
  209.     If you want a button other than button #1 to act as the default button,
  210.     don't forget to supply your own filterProc that translates RETURN to
  211.     the correct item number.
  212. --------------------------------------------------------------------------------*/
  213. pascal short InstallDefaultOutline(DialogPtr dlog, short button)
  214. {
  215.     short            userItem;
  216.     short            type;
  217.     Handle            item;
  218.     Rect            box;
  219.     Rect            userBox;
  220.     
  221.     userItem = AddNewUserItem( dlog );
  222.     if( userItem > 0 )
  223.     {
  224.         GetDItem(dlog, button, &type, &item, &box);
  225.         InsetRect(&box,-4,-4);
  226.         GetDItem(dlog, userItem, &type, &item, &userBox);
  227.         SetDItem(dlog, userItem, type, (Handle)DrawDefaultProc, &box );
  228.     }
  229.     
  230.     gDefaultButton = button;
  231.     gDefaultUserItem = userItem;
  232.     
  233.     return userItem;
  234. }
  235.  
  236. /*--------------------------------------------------------------------------------
  237.     Draw the thick square rectangle around the dialog item that accepts
  238.     keyboard input (see the System 7 Chooser for an example).
  239. --------------------------------------------------------------------------------*/
  240. pascal void DrawActiveItemProc(DialogPtr dlog, short item)
  241. {
  242.     short            type;
  243.     Handle            itemHandle;
  244.     Rect            box;
  245.     PenState        saveState;
  246.     
  247.     GetPenState( &saveState );
  248.     GetDItem(dlog, item, &type, &itemHandle, &box);
  249.     InsetRect(&box,1,1);
  250.     PenNormal();
  251.     PenSize(2,2);
  252.     FrameRect(&box);
  253.     SetPenState( &saveState );
  254. }
  255.  
  256. /*--------------------------------------------------------------------------------
  257.     This function creates a useritem around the specified button & installs
  258.     a drawing proc that draws the default border around it.
  259.     
  260.     Note:
  261.     
  262.     This routine insets the button rect by -4, & the drawing proc insets this
  263.     value again by 1.  This may seem strange, but if we just inset the rect
  264.     by -3 in this routine, then the same 'MoveOutline' function could not be
  265.     used for both default button outlines and active item outlines.
  266.     (MoveOutline always insets the item rect by -4)
  267. --------------------------------------------------------------------------------*/
  268. pascal short InstallActiveItemOutline(DialogPtr dlog, short button)
  269. {
  270.     short            userItem;
  271.     short            type;
  272.     Handle            item;
  273.     Rect            box;
  274.     Rect            userBox;
  275.     
  276.     userItem = AddNewUserItem( dlog );
  277.     if( userItem > 0 )
  278.     {
  279.         GetDItem(dlog, button, &type, &item, &box);
  280.         InsetRect(&box,-4,-4);
  281.         GetDItem(dlog, userItem, &type, &item, &userBox);
  282.         SetDItem(dlog, userItem, type, (Handle)DrawActiveItemProc, &box );
  283.     }
  284.     
  285.     return userItem;
  286. }
  287.  
  288. /*--------------------------------------------------------------------------------
  289.     Move a userItem around the appropriate button.
  290.     
  291.     This function should be used in conjunction with InstallDefaultOutline and
  292.     InstallActiveItemOutline to move the default button / active item indicator.
  293. --------------------------------------------------------------------------------*/
  294. pascal void MoveOutline(DialogPtr dlog, short userItem, short button)
  295. {
  296.     short            type;
  297.     Handle            item;
  298.     Rect            box;
  299.     Rect            userBox;
  300.  
  301.     GetDItem(dlog, button, &type, &item, &box);
  302.     InsetRect(&box,-4,-4);
  303.     GetDItem(dlog, userItem, &type, &item, &userBox);
  304.     SetDItem(dlog, userItem, type, item, &box );
  305.     /*
  306.     // Erase the old box & invalidate the old and new
  307.     // locations to force a redraw
  308.     */
  309.     EraseRect( &userBox );
  310.     InvalRect( &userBox );
  311.     InvalRect( &box );
  312.     
  313.     if( userItem == gDefaultUserItem )
  314.         gDefaultButton = button;
  315. }
  316.  
  317. /*----------------------------------------------------------------------
  318.     Set the item handle of a dialog item (particularly useful for
  319.     useritems)
  320. ----------------------------------------------------------------------*/
  321. pascal void SetItemHandle( DialogPtr dlog, short whichItem, Handle newItem )
  322. {
  323.     short            type;
  324.     Handle            item;
  325.     Rect            box;
  326.     
  327.     GetDItem(dlog,whichItem,&type,&item,&box);
  328.     SetDItem(dlog,whichItem,type,newItem,&box);
  329. }
  330.  
  331. /*--------------------------------------------------------------------------------
  332.     Returns the location of a given dialog item
  333. --------------------------------------------------------------------------------*/
  334. Point GetItemPoint( DialogPtr dlog, short itemNum )
  335. {
  336.     Point        loc;
  337.     short        type;
  338.     Handle        item;
  339.     Rect        box;
  340.     
  341.     GetDItem(dlog,itemNum, &type, &item, &box);
  342.     loc.h = box.left;
  343.     loc.v = box.top;
  344.     return( loc );
  345. }
  346.  
  347. /*--------------------------------------------------------------------------------
  348.     This simple routine will enable or disable a button
  349. --------------------------------------------------------------------------------*/
  350. pascal void EnableButton(DialogPtr dlog, short button,Boolean enable)
  351. {
  352.     ControlHandle        buttonHandle;
  353.     short                type;
  354.     Rect                box;
  355.     
  356.     GetDItem(dlog,button,&type,(Handle*)&buttonHandle,&box);
  357.     HiliteControl(buttonHandle, enable ? 0 : 255);
  358. }
  359.